package service

import (
	"context"
	"errors"
	"fmt"
	"net"
	"time"
)

type TCPClient struct {
	addr string
	conn net.Conn
	Send chan []byte
}

//NewTCPClient 创建TCP客户端
func NewTCPClient(addr string) (*TCPClient, error) {
	conn, err := net.DialTimeout("tcp", addr, time.Second)
	if err != nil {
		return nil, err
	}
	return &TCPClient{
		addr: addr,
		conn: conn,
		Send: make(chan []byte),
	}, nil
}

func (t *TCPClient) Write() {
	defer func() {
		t.Close()
	}()
	for {
		select {
		case message, ok := <-t.Send:
			if !ok {
				return
			}
			_, err := t.conn.Write(message)
			if errors.Is(err, net.ErrClosed) {
				fmt.Println("write:", string(message))
				t.Reconnection()
			}

		}
	}
}

func (t *TCPClient) Read() {
	defer func() {
		t.Close()
	}()
	readBuf := make([]byte, 1024)
	for {
		_, err := t.conn.Read(readBuf)
		if errors.Is(err, net.ErrClosed) {
			t.Reconnection()
		}
	}
}

// Reconnection 重连.
func (t *TCPClient) Reconnection() {
	conn, err := net.Dial("tcp", t.addr)
	if err != nil {
		t.conn = conn
	}
}

func (t *TCPClient) SendData(data []byte) error {
	_, err := t.conn.Write(data)
	return err
}

func (t *TCPClient) RequestData(data []byte) ([]byte, error) {
	err := t.SendData(data)
	if err != nil {
		return nil, err
	}
	ctx, _ := context.WithTimeout(context.Background(), time.Second*1)
	readBuf := make([]byte, 1024)
	done := make(chan error, 1)
	go func() {
		n, err := t.conn.Read(readBuf)
		readBuf = readBuf[:n]
		done <- err
	}()
	select {
	case err := <-done:
		return readBuf, err
	case <-ctx.Done():
		return readBuf, ctx.Err()
	}
}

func (t *TCPClient) Close() {
	if t.conn != nil {
		t.conn.Close()
	}
}
